package com.excilys.formation.project.repository.impl;

import java.util.SortedSet;
import java.util.TreeSet;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.validation.constraints.Min;

import org.joda.time.Interval;
import org.springframework.stereotype.Repository;

import com.excilys.formation.project.entities.Transaction;
import com.excilys.formation.project.repository.TransactionDAO;

/**
 * 
 * @author excilys
 * 
 */
@Repository
public class TransactionDAOImpl implements TransactionDAO {
	/**
	 * EntityManager.
	 */
	@PersistenceContext
	private EntityManager em;

	/**
	 * Requète principale pour récupérer les virements.
	 */
	private StringBuilder virementQSB;
	{
		virementQSB = new StringBuilder("FROM Transaction t INNER JOIN t.operations o INNER JOIN o.compte c INNER JOIN o.typeOperation ");
		virementQSB.append("WHERE c.client.id = :id ");
		virementQSB.append("AND o.typeOperation.libelle = 'VIREMENT' ");
		virementQSB.append("AND o.montant < 0 ");
		virementQSB.append("AND o.date BETWEEN :date_debut AND :date_fin ");
	}

	@Override
	public void save(Transaction transaction) {
		Transaction lTransaction = em.merge(transaction);
		em.persist(lTransaction);
		transaction.setId(lTransaction.getId());
	}

	@SuppressWarnings("unchecked")
	@Override
	public SortedSet<Transaction> getVirementsEmisByClientByTimeInterval(long clientId, Interval interval, @Min(0) int offset, @Min(0) int limit) {
		StringBuilder jpqlQSB = new StringBuilder("FROM Transaction t2 INNER JOIN FETCH t2.operations o INNER JOIN FETCH o.compte ");
		jpqlQSB.append("WHERE t2.id IN (");
		jpqlQSB.append("SELECT t.id ");
		jpqlQSB.append(virementQSB);
		jpqlQSB.append("ORDER BY o.date ");
		jpqlQSB.append(")");
		Query q = em.createQuery(jpqlQSB.toString());
		q.setParameter("id", clientId);
		q.setParameter("date_debut", interval.getStart());
		q.setParameter("date_fin", interval.getEnd());
		q.setFirstResult(offset);
		q.setMaxResults(limit);

		return new TreeSet<Transaction>(q.getResultList());
	}

	@Override
	public long getCountVirementsClientByTimeInterval(long clientId, Interval interval) {
		StringBuilder jpqlQSB = new StringBuilder("SELECT COUNT(t.id) ");
		jpqlQSB.append(virementQSB);
		Query q = em.createQuery(jpqlQSB.toString());
		q.setParameter("id", clientId);
		q.setParameter("date_debut", interval.getStart());
		q.setParameter("date_fin", interval.getEnd());
		return ((Long) q.getSingleResult());
	}

}
